/*
Copyright (C) 2010 Ronie Salgado

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "stdafx.h"
#include "QTexturePanel.h"
#include "QDraw.h"
#include "Texture.h"
#include "Game.h"

BEGIN_EVENT_TABLE(QTexturePanel, wxPanel)
	EVT_PAINT(QTexturePanel::OnPaint)
	EVT_SIZE(QTexturePanel::OnSize)
END_EVENT_TABLE();

QTexturePanel::QTexturePanel(wxWindow *parent, int id, wxPoint position,
		wxSize size)
	: wxPanel(parent, id, position, size)
{
	texture = NULL;
	invalid = false;
}

QTexturePanel::~QTexturePanel()
{
}

Texture *QTexturePanel::GetTexture() const
{
	return texture;
}

void QTexturePanel::SetTexture(Texture *texture)
{
	// Check that we are actually changing the texture.
	if(texture != this->texture || invalid)
	{
		this->texture = texture;

		// Recreate the draw image.
		RecreateImage();

		// Refresh panel.
		Refresh();
	}
}

void QTexturePanel::OnPaint(wxPaintEvent &event)
{
	// Create the paint dc.
	wxPaintDC dc(this);

	// Now draw the texture, if it exists.
	if(texture && !invalid)
	{
		// Scale the texture.
		wxRect rect = GetClientRect();
		float xscale = float(rect.width)/float(texture->width);
		float yscale = float(rect.height)/float(texture->height);
		dc.SetUserScale(xscale, yscale);

		// Blit the texture.
		dc.Blit(0, 0, texture->width, texture->height, &memDC, 0, 0);
	}
	else
	{
		// Draw a black background.
		wxBrush bg;
		bg.SetColour(0,0,0);
		dc.SetBackground(bg);
		dc.Clear();
	}
}

void QTexturePanel::OnSize(wxSizeEvent &event)
{
	Refresh();
}

void QTexturePanel::RecreateImage()
{
	if(!texture)
		return;

	// First cache the texture.
	if(!texture->Cache())
	{
		// Failed to cache.
		// Set the invalid flag.
		invalid = true;
		return;
	}

	// Unset the invalid flag
	invalid = false;

	int width = texture->width;
	int height = texture->height;

	// Create the image.
	wxImage image;
	image.Create(width, height, false);

	unsigned char *dst = image.GetData();
	unsigned char *src = (unsigned char *)texture->surface;
	int numpixels = width*height;
	if(texture->bits == 8)
	{
		// TODO: Use grayscale when there isn't a palette.
		const wxString &palDef =texture->game->GetPalDef();
		pal.Load(palDef, QDraw::textureGamma);

		for(int i = 0; i < numpixels; i++)
		{
			dst[i*3] = pal.pal[src[i]].red;
			dst[i*3+1] = pal.pal[src[i]].green;
			dst[i*3+2] = pal.pal[src[i]].blue;
		}
	}
	else if(texture->bits == 16)
	{
		unsigned short *src16 = (unsigned short*)src;
		for(int i = 0; i < numpixels; i++)
		{
			unsigned short pix = src16[i];
			dst[i*3] = (pix & 0xF800) >> 8;
			dst[i*3+1] = (pix & 0x07E0) >> 3;
			dst[i*3+2] = (pix & 0x001F) << 3;
		}
	}
	else if(texture->bits == 24)
	{
		memcpy(dst, src, numpixels*3);
	}
	else if(texture->bits == 32)
	{
		// Ignore the alpha channel.
		for(int i = 0; i < numpixels; i++)
		{
			dst[i*3] = src[i*4];
			dst[i*3+1] = src[i*4+1];
			dst[i*3+2] = src[i*4+2];
		}
	}

	bitmap = wxBitmap(image);
	memDC.SelectObject(bitmap);
}

